import numpy as np
import scipy as sp
from sklearn import svm
import crs

def serialize_oneclasssvm(model):
    serialized_model = {
        'meta':'OneClassSVM',
        'class_weight':model.class_weight.tolist(),
        'coef0_':model.coef0_,
        'degree_':model.degree_,
        'epsilon_':model.epsilon_,
        'kernel_':model.kernel_,
        'n_features_in':model.n_features_in_,
        'n_iter_':model.n_iter_,
        'nu_':model.nu,
        'offset_':model.offset_.tolist(),
        'tol_':model.tol,
        'support_':model.support_.tolist(),
        'n_support_':model.n_support_.tolist(),
        'intercept_':model.intercept_.tolist(),
        'shape_fit_':model.shape_fit_,
        'gamma_':model.gamma_,
        'params_':model.get_params(),
    }

    if isinstance(model.support_vectors_,sp.sparse.csr_matrix):
        serialized_model['support_vectors_'] = crs.serialize_crs_matrix(model.support_vectors_)
    elif isinstance(model.support_vectors_,np.ndarray):
        serialized_model['support_vectors_'] = model.support_vectors_.tolist()
    
    if isinstance(model.dual_coef_,sp.sparse.csr_matrix):
        serialized_model['dual_coef_'] = crs.serialize_crs_matrix(model.dual_coef_)
    elif isinstance(model.dual_coef_,np.ndarray):
        serialized_model['dual_coef_'] = model.dual_coef_.tolist()

    if isinstance(model._dual_coef_,sp.sparse.csr_matrix):
        serialized_model['_dual_coef_'] = crs.serialize_crs_matrix(model._dual_coef_)
    elif isinstance(model._dual_coef_,np.ndarray):
        serialized_model['_dual_coef_'] = model._dual_coef_.tolist()
    return serialized_model



def deserialize_oneclasssvm(model_dict):
    model = svm.OneClassSVM(**model_dict['params'])
    model.shape_fit_ = model_dict['shape_fit_']
    model._gamma = model_dict['gamma']
    model.coef0 = model_dict['coef0']
    model.degree = model_dict['degree']
    model.epsilon = model_dict['epsilon']
    model.kernel = model_dict['kernel']
    model.n_features_in_ = model_dict['n_features_in']
    model.n_iter_ = model_dict['n_iter_']
    model.nu = model_dict['nu_']
    model.offset_ = np.array(model_dict['offset_']).astype(np.float64)
    model.tol_ = model_dict['tol_']
    model.calss_weight_ = np.array(model_dict['calss_weight_']).astype(np.float64)
    model.support_ = np.array(model_dict['support_']).astype(np.int32)
    model.n_support_ = np.array(model_dict['n_support_']).astype(np.int32)
    model.intercept_ = np.array(model_dict['intercept_']).astype(np.float64)

    if 'meta' in model_dict['support_vectors_'] and model_dict['support_vectors_']['meta'] == 'csr':
        model.support_vectors_ = crs.deserialize_crs_matrix(model_dict['support_vectors_']).astype(np.float64)
        model._sparse = True
    else:
        model.support_vectors_ = np.array(model_dict['support_vectors_']).astype(np.float64)
        model._sparse = False

    if 'meta' in model_dict['dual_coef_'] and model_dict['dual_coef_']['meta'] == 'csr':
        model.dual_coef_ = crs.deserialize_crs_matrix(model_dict['dual_coef_']).astype(np.float64)
    else:
        model.dual_coef_ = np.array(model_dict['dual_coef_']).astype(np.float64)

    if 'meta' in model_dict['_dual_coef_'] and model_dict['_dual_coef_']['meta'] == 'csr':
        model._dual_coef_ = crs.deserialize_crs_matrix(model_dict['_dual_coef_']).astype(np.float64)
    else:
        model._dual_coef_ = np.array(model_dict['_dual_coef_']).astype(np.float64)

    return model

    


def serialize_svm(model):
    serialized_model = {
        'meta':'svm',
        'class_weight_':model.class_weight_.tolist(),
        'classes_':model.classes_.tolist(),
        'support_':model.support_.tolist(),
        'n_support_':model.n_support_.tolist(),
        'intercept_':model.intercept_.tolist(),
        'probA_':model.probA_.tolist(),
        'probB_':model.probB_.tolist(),
        '_intercept_':model._intercept_.tolist(),
        'shape_fit_':model.shape_fit_,
        '_gamma':model._gamma,
        'params_':model.get_params(),
    }

    if isinstance(model.support_vectors_,sp.sparse.csr_matrix):
        serialized_model['support_vectors_'] = crs.serialize_crs_matrix(model.support_vectors_)
    elif isinstance(model.support_vectors_,np.ndarray):
        serialized_model['support_vectors_'] = model.support_vectors_.tolist()

    if isinstance(model.dual_coef_,sp.sparse.csr_matrix):
        serialized_model['dual_coef_'] = crs.serialize_crs_matrix(model.dual_coef_)
    elif isinstance(model.dual_coef_,np.ndarray):
        serialized_model['dual_coef_'] = model.dual_coef_.tolist()

    if isinstance(model._dual_coef_,sp.sparse.csr_matrix):
        serialized_model['_dual_coef_'] = crs.serialize_crs_matrix(model._dual_coef_)
    elif isinstance(model._dual_coef_,np.ndarray):
        serialized_model['_dual_coef_'] = model._dual_coef_.tolist()

    return serialized_model

def deserialize_svm(model_dict):
    model = svm.SVC(**model_dict['params_'])
    model.shape_fit_ = model_dict['shape_fit_']
    model._gamma = model_dict['_gamma']
    model.class_weight_ = np.array(model_dict['class_weight_']).astype(np.float64)
    model.classes_ = np.array(model_dict['classes_'])
    model.support_ = np.array(model_dict['support_']).astype(np.int32)
    model.n_support_ = np.array(model_dict['n_support_']).astype(np.int32)
    model.intercept_ = np.array(model_dict['intercept_']).astype(np.float64)
    model.probA_ = np.array(model_dict['probA_']).astype(np.float64)
    model.probB_ = np.array(model_dict['probB_']).astype(np.float64)
    model._intercept_ = np.array(model_dict['_intercept_']).astype(np.float64)

    if 'meta' in model_dict['support_vectors_'] and model_dict['support_vectors_']['meta'] == 'csr':
        model.support_vectors_ = crs.deserialize_crs_matrix(model_dict['support_vectors_']).astype(np.float64)
        model._sparse = True    
    elif isinstance(model.support_vectors_,np.ndarray):
        model.support_vectors_ = np.array(model_dict['support_vectors_']).astype(np.float64)
        model._sparse = False

    if 'meta' in model_dict['dual_coef_'] and model_dict['dual_coef_']['meta'] == 'csr':
        model.dual_coef_ = crs.deserialize_crs_matrix(model_dict['dual_coef_']).astype(np.float64)
    else:
        model.dual_coef_ = np.array(model_dict['dual_coef_']).astype(np.float64)    

    if 'meta' in model_dict['_dual_coef_'] and model_dict['_dual_coef_']['meta'] == 'csr':
        model._dual_coef_ = crs.deserialize_crs_matrix(model_dict['_dual_coef_']).astype(np.float64)
    else:
        model._dual_coef_ = np.array(model_dict['_dual_coef_']).astype(np.float64)

    return model



